package com.webservice.impl.factory;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.webservice.dao.Pub;
import com.webservice.dao.PubBaseDao;
import com.webservice.dao.factory.IntoStoreDao;
import com.webservice.service.IBaseService;
import com.webservice.utils.DateTimeTool;
import com.webservice.utils.UUIDUtil;
import com.webservice.utils.VOXMLMapping;
import com.webservice.vo.factory.IntoProductVO;
import com.webservice.vo.factory.IntoSeriVO;
import com.webservice.vo.factory.IntoStockInLogVo;
import com.webservice.vo.factory.IntoStoreAggVO;
import com.webservice.vo.impl.ReturnMsgVo;

/***
 * 意向入库单（WMS->B2B）
 * @author chxb 
 * 处理逻辑
 * 1.校验xml是否正确 
 * 2.解析xml转化为vo 
 * 3.记录日志信息 
 * 4.校验数据 
 * 5.改变库存，更改串码状态
 * 6.记录返回日志 
 * 7.返回数据
 */
@Service("F0001")
public class IntoStoreService implements IBaseService {
	private static Logger logger = Logger.getLogger(IntoStoreService.class);
	private static List<String> updateList=new ArrayList<String>();


	@Autowired
	@Qualifier("IntoStoreDao")
	private IntoStoreDao intoStoreDao;
	
	@SuppressWarnings("finally")
	@Override
	@Transactional(value = "txManager", isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = { Exception.class })
	public String returnData(String xml, PubBaseDao baseDao, String ip)throws Exception {
		updateList.clear();
		IntoStoreAggVO ss = null;
		String content = null;
		String rexml = null;
		String intoUUID = UUIDUtil.getUUID();
		String outUUID = UUIDUtil.getUUID();
		// 成对标志
		String pairflag = DateTimeTool.getDateTimeString(new Date(),"yyyymmddHHmmss:sss").replace(":", "");
		try {
			ss = (IntoStoreAggVO)VOXMLMapping.fromXML(xml, IntoStoreAggVO.class, null);// xml解析
			Pub.insertLog(baseDao, intoUUID, ip, "11", ss.getIntocode(), xml, "into", pairflag,"0");
			// 校验数据
			Map<String,String> map=new HashMap<String,String>();
			map.put("code", "intocode");
			rexml = checkData(ss, baseDao,map);
			if(null==rexml){
				if(changeStore(baseDao)){
					rexml = Pub.returnInfo(ss.getIntocode(), 0, "成功", map);
					//数据记录
					boolean flag=getIntoStoreDao().updatePurposeStock(ss);//记录意向入库的时间和产品的数量
					//List<IntoStockInLogVo> list=getIntoStoreDao().getPurposeStockDetailCode(ss);
					if(flag){
					getIntoStoreDao().insertWmsPurposeStockinLog(ss);//意向入库明细继续记录
					}
				}
			}
			Pub.insertLog(baseDao, outUUID, ip, "11", ss.getIntocode(), rexml, "out", pairflag,"1");
			ReturnMsgVo rmv =  (ReturnMsgVo) VOXMLMapping.fromXML(rexml, ReturnMsgVo.class, null);
			if(rmv.getResult() == 0){
				Pub.insertDealResultLog(baseDao, outUUID, "WMS", "B2B", "成功", "厂家补货处理成功");
			}else{
				Pub.insertDealResultLog(baseDao, outUUID, "WMS", "B2B", "处理异常", rmv.getMsg());
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			content = "请求的xml转化错误" + e.getMessage();
			Pub.insertLog(baseDao, intoUUID, ip, "11", ss.getIntocode()==null?null:ss.getIntocode(), xml, "into", pairflag,"0");
			rexml = Pub.returnInfo(null, -1, "失败：" + content, null);
			Pub.insertLog(baseDao, outUUID, ip, "11", ss.getIntocode()==null?null:ss.getIntocode(), rexml, "out", pairflag,"1");
			throw new Exception(rexml);
		}finally{
			return rexml;
		}
	}
	
	/***
	 * 检查数据
	 * @param ss
	 * @return  
	 * 仓库信息必须存在，并且不能为空  
	 * 供应商必须存在，并且不能为空  
	 * 产品必须存在，并且不能为空  产品数量不能为空，并且大于0  
	 * 串码信息不能为空
	 * @throws Exception 
	 */
	public String checkData(IntoStoreAggVO ss,PubBaseDao baseDao,Map<String,String> map) throws Exception {
		return checkStore(ss, baseDao,map);
	}

	/***
	 * 检查仓库
	 * @param ss
	 * @param baseDao
	 * @return
	 * @throws Exception
	 */
	public String checkStore(IntoStoreAggVO ss,PubBaseDao baseDao,Map<String,String> map) throws Exception{
		String storeCode=ss.getStorecode();
		if(null==storeCode){//仓库不能为空
			return Pub.returnInfo(ss.getIntocode(), -1, "失败：仓库信息为空", map);
		}else{//校验仓库是否存在
			String sql="select pk_store from bi_store where storecode=?";
			Object[] parms=new Object[]{storeCode};
			logger.debug("查询sql："+Pub.logSQL(sql, parms));
			List<String> list=baseDao.getList(sql, parms, "pk_store");
			if(null==list||list.size()==0)return Pub.returnInfo(ss.getIntocode(), -1,"失败：仓库"+storeCode+"不存在", map);
			return checkSupply(ss, baseDao,storeCode,map);
		}
	}
	
	/***
	 * 检查供应商
	 * @param ss
	 * @param baseDao
	 * @return
	 */
	@Transactional(value = "txManager", isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = { Exception.class })
	public String checkSupply(IntoStoreAggVO ss,PubBaseDao baseDao,String storeCode,Map<String,String> map){
		List<IntoProductVO> products=ss.getProducts(); 
		if(null==products||products.size()==0)return Pub.returnInfo(ss.getIntocode(), -1, "失败：产品信息为空", map);
		for(IntoProductVO product:products){
			BigDecimal supplyid=product.getSupplyid();//供应商
			String productcode=product.getProductcode();//产品
			BigDecimal quantity=product.getQuantity();//数量
			List<IntoSeriVO> serials=product.getSerials();//串码信息
			if(null==supplyid){
				return Pub.returnInfo(ss.getIntocode(), -1, "失败：供应商"+supplyid+"为空", null);
			}
			String sql="select name from supply where id=?";
			Object[] parms=new Object[]{supplyid};
			logger.debug("查询sql："+Pub.logSQL(sql, parms));
			List<String> list = baseDao.getList( sql, parms,"name");
			if(null==list||list.size()==0)return Pub.returnInfo(ss.getIntocode(), -1, "失败：供应商"+supplyid+"不存在", map);
			String str=checkProduct(ss, baseDao, productcode,quantity,serials, storeCode,supplyid,map);
			if(null!=str)return str;
			/**
			 * 仓库是否存在供应商
			 */
			String comSql=" select sp.id from store_product sp where sp.pk_stordoc=? and sp.productid=? and sp.supplyid=?  ";
			Object[] comParms=new Object[]{storeCode,productcode,supplyid};
			List<String> comList=baseDao.getList( comSql, comParms,"id");
			logger.debug("查询sql："+Pub.logSQL(comSql, comParms));
			if(null==comList||comList.size()==0){
//				return Pub.returnInfo(ss.getIntocode(), -1, "失败：仓库"+pk_store+"不存在产品"+productcode+" 供应商"+supplyid, null);
				String insertSql=" INSERT INTO STORE_PRODUCT (ID, PK_STORDOC, PRODUCTID, QUANTITY, ALLOCATABLE, ONWAYNUMBER, SUPPLYID) values (SEQ_STORE_PRODUCT.NEXTVAL, ?, ?, ?, 0, null, ?) ";
				Object[] insertParms=new Object[]{storeCode,productcode,quantity,supplyid};
				logger.debug("更新sql："+Pub.logSQL(insertSql, insertParms));
				baseDao.getJdbcTemplate().update(insertSql, insertParms);
			}
		}
		return null;
	}
	
	/***
	 * 检查产品
	 * @param ss
	 * @param baseDao
	 * @return
	 */
	public String checkProduct(IntoStoreAggVO ss,PubBaseDao baseDao,String productcode,BigDecimal quantity,List<IntoSeriVO> serials,String storeCode,BigDecimal supplyid,Map<String,String> map){
		if(null==productcode)return Pub.returnInfo(ss.getIntocode(), -1, "失败：产品信息为空", map);
		String sql=" select productid from product_main where productid=? ";
		Object[] parms=new Object[]{productcode};
		logger.debug("查询sql："+Pub.logSQL(sql, parms));
		List<String> list = baseDao.getList( sql, parms,"productid");
		if(null==list||list.size()==0)return Pub.returnInfo(ss.getIntocode(), -1, "失败：产品"+productcode+"不存在", map);//产品不能为空
		if(null==quantity)return Pub.returnInfo(ss.getIntocode(), -1, "失败：产品数量为空", map);//产品数量不能为空
		String productid=list.get(0);//产品数量
		//if(null==serials||serials.size()==0)return Pub.returnInfo(ss.getIntocode(), -1, "失败：串码信息为空", null);//串码信息
		/*if(serials != null && serials.size() > 0){
			String sers=checkSerials(baseDao, ss.getIntocode(), serials, quantity, productcode,map);
			if(null!=sers)return sers;
		}*/
		//更新库存sql
		String updatesql=" update store_product set allocatable=allocatable+"+quantity+" where pk_stordoc='"+storeCode+"' and productid="+productid+" and supplyid="+supplyid+" ";
		updateList.add(updatesql);
		//检查串码
		return null;
	}
	
	/***
	 * 校验串码数量与产品数量相同
	 * @param baseDao 数据库实例
	 * @param ordercode 订单号
	 * @param serials 串码
	 * @param quantity 数量
	 * @return
	 */
	public String checkSerials(PubBaseDao baseDao,String ordercode,List<IntoSeriVO> serials,BigDecimal quantity,String productcode,Map<String,String> map){
		if(quantity.compareTo(new BigDecimal(serials.size()))!=0)return Pub.returnInfo(ordercode, -1, "失败：产品"+productcode+"数量与串码数量不同", map);
		return null;
	}
	
	/**
	 * 添加厂家入库信息
	 * @param ss
	 * @param baseDao
	 * @return
	 */
	public boolean addIntoStore(IntoStoreAggVO ss,PubBaseDao baseDao){
		return false;
	}
	
	/***
	 * 更新库存
	 * @return
	 */
	public boolean changeStore(PubBaseDao baseDao) {
		if(updateList.size()==0)return true;
		String[] sql=new String[updateList.size()];
		sql=updateList.toArray(sql);
		updateList.clear();
		int[] rows=baseDao.getJdbcTemplate().batchUpdate(sql);//更新库存
		return rows.length>0?true:false;
	}

	public IntoStoreDao getIntoStoreDao() {
		return intoStoreDao;
	}

	public void setIntoStoreDao(IntoStoreDao intoStoreDao) {
		this.intoStoreDao = intoStoreDao;
	}
}
